/***************************************************************************
* Mainlib.cpp
*
*  July 2007
*  Copyright  2007  RuijinZheng,China
*  Email mebetop@126.com
****************************************************************************/

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include "Dispatcher.hpp"
static Dispatcher dispatcher;
/// the object "dispatcer" is a  bootstrap,it will do many importante things when the lib being loaded.
Udpflealayer *udp=NULL;
extern "C" int connect(int  sockfd, const struct sockaddr *serv_addr, socklen_t  addrlen){
       if(!(Dispatcher::Suitablesocket(sockfd,serv_addr))){
             return (dispatcher.Getorigconnect())(sockfd,serv_addr,addrlen);
        }

       int flags = fcntl(sockfd, F_GETFL);
       if(Dispatcher::Setsockblock(sockfd,flags)==false){
    	   Lowlayer::Errordeliver("failed to set socket block",strerror(errno));
    	   return -1  ;
       }
      int ret=-1;
       Lowlayer * layer=NULL;
       try{
             layer= dispatcher.Createlayer();
             if((ret = layer->Connectflea(sockfd,serv_addr,dispatcher.Getproxyservers()))<0){
            	    Lowlayer::Errordeliver("failed to connect to proxy server",strerror(errno));
            	    return ret;
              }
             cout<<"----------------------------------"<<endl;
             cout<<"socket : "<<sockfd<<" has established connection to proxy server"<<endl;
             cout<<"----------------------------------"<<endl;
        }
       catch(const string &s){
             Lowlayer::Errordeliver(s,strerror(errno));
        }
       catch(const char *e){
             Lowlayer::Errordeliver(e,strerror(errno));
        }
       catch(...) {
             Lowlayer::Errordeliver("Unkown error ocured",
                      strerror(errno));
       }
      Dispatcher::Restoresock(sockfd,flags);
       return ret;
} 
extern "C" ssize_t recvfrom(int sockfd,void *buff,size_t buflen,int flags,sockaddr *from,socklen_t *fromlen){
    if(udp==NULL){
   	  //if it is going on a DNS  resolution or etc. ,I should  ignore it. 
          return (dispatcher.Getorigrecvfrom())(sockfd,buff,buflen,flags,from,fromlen);
    }
     ssize_t ret=-1;
     try{
    	     
	         ret = udp->Recvfromflea(sockfd,buff,buflen,flags,from,fromlen);

     	      return ret;
       }
       catch(const string &s){
            Lowlayer::Errordeliver(s,strerror(errno));
       }
       catch(const char *c){
            Lowlayer::Errordeliver(c,strerror(errno));
       }
       catch(...){
            Lowlayer::Errordeliver("Unkown error ocured",strerror(errno));
       }
}
extern "C" ssize_t sendto(int sockfd,const void*buff,size_t buflen,int flags,const sockaddr  *to,socklen_t  tolen){
       if(udp==NULL){
    	    udp = dispatcher.Createudplayer();
        }
       ssize_t ret=-1;
       try{
    	      Udpproxy *responsestruct;
    	      responsestruct =udp->Getreadyresponseaddr(sockfd);
     	      if(responsestruct==NULL){
     	    	   sockaddr_in *localaddr=udp->Getbindedaddr(sockfd);
     	    	   responsestruct=udp->GetUdplayerReady(sockfd,(sockaddr *)localaddr,dispatcher.Getproxyservers());
     	    	  	if(responsestruct==NULL){
     	    	  			return -1;
     	    	  	}else{
      	            ret = udp->Sendtoflea(sockfd,buff,buflen,flags,to,tolen,responsestruct);
      	     	     return ret;
     	    	  	}
     	      }else{
     	             ret = udp->Sendtoflea(sockfd,buff,buflen,flags,to,tolen,responsestruct);
     	     	      return ret;
     	      }
       }
       catch(const string &s){
            Lowlayer::Errordeliver(s,strerror(errno));
       }
       catch(const char *c){
            Lowlayer::Errordeliver(c,strerror(errno));
       }
       catch(...){
            Lowlayer::Errordeliver("Unkown error ocured",strerror(errno));
       }
}

